<html>
<head>
  <title>node.js 2.4——http模块</title>
  <basefont face="宋体" size="2" />
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
  <meta name="exporter-version" content="YXBJ Windows/607344 (zh-CN, DDL); Windows/10.0.0 (Win64); EDAMVersion=V2;"/>
  <meta name="content-class" content="yinxiang.superNote"/>
  <style>
    body, td {
      font-family: 宋体;
      font-size: 16pt;
    }
  </style>
</head>
<body>
<a name="2743"/>
<h1>node.js 2.4——http模块</h1>

<div><span><h1>1 简介</h1><ul><li><div>用于创建服务器或者客户端</div></li><li><div>需要使用http模块</div></li><li><div>如果要获取本机的ip地址：</div></li><ul><li><div>该方式也有一定问题。</div></li></ul></ul><div style="--en-codeblock:true;--en-codeblockLanguage:clike;box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.14902); background-position: initial initial; background-repeat: initial initial; margin-top: 6px;">const os = require('os');
///获取本机ip///
function getIPAdress() {
    // 返回一个对象，对象中包含已分配了的网络接口
    // 内部有多个对象，每个对象对应一种网络接口类型
    let interfaces = os.networkInterfaces();
    for (var devName in interfaces) {
        // devName为一种网络类型
        // 下面这句话可以获取该网络类型下所有已分配的网络接口
        // 一般有两种，一种是IPv4，另一种是IPv6
        let iface = interfaces[devName]; // 如果是wifi的话，这里可以直接将devName替换为'WLAN'
        for (let i = 0; i &lt; iface.length; i++) {
            // 下面这句话可以获得网络接口对象
            // 它有以下属性
            // 【address】:接口地址，或者是物理地址
            // 【family】:接口种类'IPv6'或者'IPv4'
            // 【mac】:网络接口的 MAC 地址
            // 【netmask】:子网掩码
            // 【internal】:如果网络接口是不可远程访问的环回接口或类似接口，则为 true，否则为 false。
            let alias = iface[i];
            if (alias.family === 'IPv4' &amp;&amp; alias.address !== '127.0.0.1' &amp;&amp; !alias.internal) {
                  // 找到 IPv4的ip地址
                  // 要求该ip地址不能为&quot;127.0.0.1&quot;
                  return alias.address;
            }
        }
    }
}</div><div><br/></div><h1>2 简单的服务端示例</h1><div style="--en-codeblock:true;--en-codeblockLanguage:javascript;box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.14902); background-position: initial initial; background-repeat: initial initial; margin-top: 6px;">// 引入http模块
const http = require('http');

// 创建一个服务器
var server = http.createServer()
// 为服务器注册客户端请求响应事件
server.on('request',()=&gt;{
  console.log(&quot;收到客户端请求了！&quot;)
})
// 绑定端口号
server.listen(3000,()=&gt;{
  console.log(&quot;服务端启动成功。可以通过http://127.0.0.1:3000 来访问&quot;)
})</div><ul><li><div>简写版</div></li><ul><li><div>支持链式调用</div></li></ul></ul><div style="--en-codeblock:true;--en-codeblockLanguage:clike;box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.14902); background-position: initial initial; background-repeat: initial initial; margin-top: 6px;">const http = require('http');
const fs = require('fs');

http.createServer((req,res)=&gt;{
  res.end('hello')
}).listen(3000,()=&gt;{
  console.log(&quot;running&quot;);
});</div><h1>3 服务端</h1><h2>3.1 相关方法</h2><ul><li><div>需要处理客户端请求，并对其进行响应。</div></li><li><div>在注册连接服务的时候： server.on('request',(request,response)=&gt;{}) 中</div></li><ul><li><div>【request】：请求响应对象</div></li><ul><li><div>【request.url】：请求路径，是ip地址后面的地址，<b>开头带着'/'</b></div></li></ul><li><div>【response】：请求响应对象</div></li><ul><li><div>【response.write(str)】：str 是请求响应的内容，如果是 html代码，会直接被渲染，它可以直接用 response.end(str)方法替代，因为必须用 end 方法结束</div></li><li><div>【response.end(str)】：<b>必须有该方法作为结束，否则客户端还是无法收到响应。</b>str 是请求响应的内容，如果是 html代码，会直接被渲染</div></li><ul><li><div><b>注意，str 只能是 string 或者 Buffer 类型(二进制)的数据。可以使用JSON对象将数组转为字符串</b></div></li><li><div>可以结合fs.readFile(文件路径,(err,data)=&gt;{})，其中data可以直接传递给res.end(data)</div></li></ul><li><div>【response.setHeader(key,value)】：设置响应头</div></li></ul></ul></ul><h2>3.2 返回html文件</h2><div style="--en-codeblock:true;--en-codeblockLanguage:clike;box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.14902); background-position: initial initial; background-repeat: initial initial; margin-top: 6px;">const http = require('http');
const fs = require('fs')
const server = http.createServer();
server.on('request',(req,res)=&gt;{
  fs.readFile('./index.html',(err,data)=&gt;{
    if(err){
      res.setHeader('Content-Type',&quot;text/plain;charset=utf-8&quot;)
      res.end(&quot;找不到文件&quot;)
    }else{
      res.setHeader('Content-Type',&quot;text/html;charset=utf-8&quot;)
      res.end(data)
    }
  })
})
server.listen(3000,()=&gt;{
  console.log(&quot;服务器建立成功，请访问:'&quot; + &quot;127.0.0.1:3000'&quot;)
})</div><h2>3.3 重定向</h2><ul><li><div>原理</div></li><ul><li><div>返回的状态码时302</div></li><li><div>响应头必须有Location字段，值为跳转的 uri 或 url</div></li></ul></ul><div style="--en-codeblock:true;--en-codeblockLanguage:javascript;box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.14902); background-position: initial initial; background-repeat: initial initial; margin-top: 6px;">res.statusCode = 302;
res.setHeader('Location','/');
res.end();</div><h2>服务监听</h2><div style="--en-codeblock:true;--en-codeblockLanguage:text/x-java;box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.14902); background-position: initial initial; background-repeat: initial initial; margin-top: 6px;">const http = require('http');
const server = http.createServer();
server.on('request', (req, res) =&gt; {
    let address = req.socket.remoteAddress
    address = address.substring(address.lastIndexOf(&quot;:&quot;)+1)
    console.log(`请求的服务器地址:${address}:${req.socket.remotePort}`)
    console.log(`请求的url:${req.url}`)
    console.log(&quot;请求方法:&quot;+req.method)
    console.log(`请求头:`)    
    console.log(req.headers)
    let body = '';
    req.on('data', function (chunk) {
        body += chunk
    });
    req.on('end', function () {
        console.log(&quot;请求体: &quot;)
        console.log(body)
    });
    res.setHeader('Content-Type', &quot;text/html;charset=utf-8&quot;)
    res.end(&quot;hello&quot;)
})

server.listen(9081, () =&gt; {
    console.log(&quot;服务器建立成功，请访问:'&quot; + &quot;127.0.0.1:9081'&quot;)
})</div><div><br/></div><h1>4 自动打开浏览器</h1><ul><li><div>需要结合child_process模块</div></li></ul><div style="--en-codeblock:true;--en-codeblockLanguage:clike;box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.14902); background-position: initial initial; background-repeat: initial initial; margin-top: 6px;">const { exec } = require('child_process');

let url = &quot;http://127.0.0.1:3000&quot;;
// 拿到当前系统的参数
switch (process.platform) {
  //mac系统使用 一下命令打开url在浏览器
  case &quot;darwin&quot;:
    exec(`open ${url}`);
  //win系统使用 一下命令打开url在浏览器
  case &quot;win32&quot;:
    exec(`start ${url}`);
  // 默认mac系统
  default:
    exec(`open ${url}`);
}</div><h1>5 客户端请求</h1><ul><li><div>简单示例</div></li></ul><div style="--en-codeblock:true;--en-codeblockLanguage:javascript;box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.14902); background-position: initial initial; background-repeat: initial initial; margin-top: 6px;">import http from 'http'
import https from 'https'

// 请求的url
let url = 'http://www.baidu.com/';
// 请求的配置
let options = {
    // 请求头的配置
    headers: {
        'Content-Type': 'application/json'
    }
}
http.get(url, options, (res) =&gt; {
    
    // 获取状态码
    const { statusCode } = res;
    // 获取请求头
    const contentType = res.headers['content-type'];

    // 判断是否有问题
    if (statusCode != 200) {
        let error = new Error('Request Failed.\n' + `Status Code: ${statusCode}`);
        console.error(error.message);
        // 消费响应数据以释放内存
        res.resume();
        return;
    }
    // 获取响应体
    let rawData = [];
    res.on('data', chunk =&gt; {
        rawData.push(chunk)
    })
    res.on('end', () =&gt; {
        // 响应体内容
        let body = rawData.join(&quot;&quot;);
        console.log(body)
    })
}).on('error', err =&gt; {
    // 出错了
    console.error(`Got error: ${err.message}`);
})</div><div><br/></div><div><br/></div><h2>工具</h2><ul><li><div>ES6版</div></li></ul><div style="--en-codeblock:true;--en-codeblockLanguage:javascript;box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.14902); background-position: initial initial; background-repeat: initial initial; margin-top: 6px;">import http from 'http'
import https from 'https'

export default {
  /**
   * get请求
   * @param {*} url:请求的url 
   * @param {Object} headers:请求头
   * @param {Boolean} isHttp:是否是http协议，false 代表使用HTTPS 
   * @returns Promise对象.then(res=&gt;{}),res中有两个元素，res.body,res.headers
   */
  get (url, headers, isHttp) {
    let _http;
    if (isHttp === undefined || isHttp) {
      _http = http
    } else {
      _http = https
    }
    // 请求的配置
    let options = {
      // 请求头的配置
      headers
    }
    return new Promise((resolve, reject) =&gt; {
      _http.get(url, options, (res) =&gt; {
        // 获取状态码
        const { statusCode } = res;
        // 判断是否有问题
        if (statusCode != 200) {
          res.resume();
          reject('Request Failed.\n' + `Status Code: ${statusCode}`)
          return;
        }
        // 获取响应体
        let rawData = [];
        let resHeaders = res.headers
        res.on('data', chunk =&gt; {
          rawData.push(chunk)
        })
        res.on('end', () =&gt; {
          // 响应体内容
          let body = rawData.join(&quot;&quot;);
          resolve({
            body,
            headers: resHeaders
          })
        })
      }).on('error', err =&gt; {
        reject(`Got error: ${err.message}`)
      })
    })
  }
}</div><ul><li><div>CommonJS版</div></li></ul><div style="--en-codeblock:true;--en-codeblockLanguage:javascript;box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.14902); background-position: initial initial; background-repeat: initial initial; margin-top: 6px;">const http = require(&quot;http&quot;);
const https = require(&quot;https&quot;);

module.exports = {
  /**
   * get请求
   * @param {String} url:请求的url
   * @param {Object} headers:请求头
   * @returns Promise对象.then(res=&gt;{}),res中有两个元素，res.body,res.headers
   */
  get(url, headers) {
    let _http;
    if(url.indexOf(&quot;https&quot;)===0){
      _http = https;
    }else{
      _http = http;
    }
    // 请求的配置
    let options = {
      // 请求头的配置
      headers,
    };
    return new Promise((resolve, reject) =&gt; {
      _http
        .get(url, options, (res) =&gt; {
          // 获取状态码
          const { statusCode } = res;
          // 判断是否有问题
          if (statusCode != 200) {
            res.resume();
            reject(&quot;Request Failed.\n&quot; + `Status Code: ${statusCode}`);
            return;
          }
          // 获取响应体
          let rawData = [];
          let resHeaders = res.headers;
          res.on(&quot;data&quot;, (chunk) =&gt; {
            rawData.push(chunk);
          });
          res.on(&quot;end&quot;, () =&gt; {
            // 响应体内容
            let body = rawData.join(&quot;&quot;);
            resolve({
              body,
              headers: resHeaders,
            });
          });
        })
        .on(&quot;error&quot;, (err) =&gt; {
          reject(`Got error: ${err.message}`);
        });
    });
  },
};</div><div><br/></div><h2>下载文件</h2><div style="--en-codeblock:true;--en-codeblockLanguage:clike;box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.14902); background-position: initial initial; background-repeat: initial initial; margin-top: 6px;">const fs = require('fs');
const https = require('https');
// File URL
const url = `https://acquirebase.com/img/logo.png`;
// Download the file
https.get(url, (res) =&gt; {
    // Open file in local filesystem
    const file = fs.createWriteStream(`logo.png`);
    // Write data into local file
    res.pipe(file);
    // Close the file
    file.on('finish', () =&gt; {
        file.close();
        console.log(`File downloaded!`);
    });
}).on(&quot;error&quot;, (err) =&gt; {
    console.log(&quot;Error: &quot;, err.message);
});</div><div><br/></div></span>
</div></body></html> 